#include "Includes.h"
#include "eeprom.h"

#pragma region //============字段=============
#define UP_BUF_SIZE		200
uint8_t UpRxBuf[UP_BUF_SIZE];
uint8_t UpFrBuf[UP_BUF_SIZE];
uint8_t UpTxBuf[UP_BUF_SIZE];
uint8_t DnRxBuf[UP_BUF_SIZE];
uint8_t DnFrBuf[UP_BUF_SIZE];
uint8_t DnTxBuf[UP_BUF_SIZE];
UartDriver *pUpUart = NULL; //上行串口对象句柄
UartDriver *pDnUart = NULL; //下行串口对象句柄
#pragma endregion

#pragma region //============变量=============
extern osThreadId _UpdateStepTaskHandle;
extern osSemaphoreId RxUp_IdleSemHandle;
extern osSemaphoreId TxUp_CpltSemHandle;
extern osSemaphoreId RxDn_IdleSemHandle;
extern osSemaphoreId TxDn_CpltSemHandle;
extern osSemaphoreId ToDnSendSemHandle;
extern osMessageQId UDP_MsgQueueHandle;
extern int Angle[];
extern uint16_t Analogs[];
extern uint8_t Keys[];
extern SysState_t SysState; //系统工作状态

//从下级传来的数据
uint16_t DnAnalogs[8];
uint8_t DnTapPos[4];
uint8_t DnKeys[4];
uint8_t KeysMask[4];
//从上级传来的指示数据
uint8_t out_analog_code; //模拟量编码:0--元码,1--规格化后编码
uint16_t UpAnalogs[12]; //模拟量
uint8_t UpLeds[4]; //每一位代表一个LED显示状态:0代表灭,1代表亮
typedef union
{
	uint8_t byte;
	struct
	{
		uint8_t now_ln	: 4;	//当前连接号
		uint8_t max_ln	: 4;	//最大连接号
	};
}link_no_t; //本机连接情况
link_no_t link_no;
#pragma endregion

#pragma region //============函数声明=============
uint8_t CheckSum(uint8_t *pByte, uint8_t len);
//描述: 获得给定帧类型的帧长度, -1=不包含sync
//返回: 0:无效帧, 其它:帧长
uint8_t GetFrameLen(uint8_t type/*[I]帧类型*/);
#pragma endregion

#pragma region //===========私有函数=============
//获得Keys[]的本地开关量的屏蔽码
void GetKeysMask(void)
{
	memset(KeysMask, 0xFF, 4);
	for (size_t i = 0; i < 10; i++)
	{
		uint8_t j = EEPROM_MSG.key_pos[i];//采集开关量的储存位:-1不采集. 低4位表示在keys[]中字节偏移量,高3位表示在字节中的偏移位置
		if (j >= 0x80) continue;
		KeysMask[j & 0x0F] ^= (1 << (j >> 4));
	}
}
//打包并向上发送连接序号帧
void PakeLinkNoFrAndTx()
{
	link_t *pt = (link_t*)UpTxBuf;
	pt->sync = SYNC;
	pt->frame_type = LINK_Fr;
	pt->device_id = EEPROM_MSG.device_id;
	pt->link_no = link_no.byte;
	pt->check_sum = CheckSum(&UpTxBuf[1], sizeof(link_t) - 2);
	
	HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_SET);
	UD_Transmit(pUpUart, UpTxBuf, sizeof(link_t));
	HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_RESET);
}
//打包向下发送的连接确认帧
void PakeLinkAffirmFr(void)
{
	SysState.isLink = 1;
	
	link_t *pt = (link_t*)DnTxBuf;
	pt->sync = SYNC;
	pt->frame_type = LINK_AFFIRM_Fr;
	pt->device_id = EEPROM_MSG.device_id;
	pt->link_no = link_no.byte;
	pt->check_sum = CheckSum(&DnTxBuf[1], sizeof(link_t) - 2);
}
//打包向上发送的配置帧
void PackConfigFr(void)
{
	config_t *pc = (config_t*)UpTxBuf;
	pc->sync = SYNC;
	pc->frame_type = UP_CONFIG_Fr;
	pc->link_no = link_no.byte;
	pc->hw_ver = HW_VER;
	memcpy(&pc->eeprom_var, &EEPROM_MSG, sizeof(EEPROM_MSG_STR) - 30 * 4);
	pc->check_sum = CheckSum(&pc->frame_type, sizeof(config_t) - 2);
	
	SysState.isFr2Tx = 1; //标记有帧要向上发送
}
//打包向上发送的系统状态帧
void PakeStatusFr(uint8_t *pTxbuf)
{
	status_frame_t *pt = (status_frame_t*)pTxbuf;
	pt->sync = SYNC;
	pt->frame_type = STATUS_Fr;
	pt->device_id = EEPROM_MSG.device_id;
	memcpy(pt->analogs, DnAnalogs, 8 * 2);
	memcpy(pt->tap_positions, DnTapPos, 4);
	memcpy(pt->keys, DnKeys, 4);
	//合并采集模拟量
	for (size_t i = 0; i < 4; i++)
	{
		uint8_t j = EEPROM_MSG.analog_pos[i];
		if (j >= 0x80) continue;
		if (j < 64) pt->analogs[j] = Analogs[i]; //更新模拟量
		else 
		{	//合并组合开关档位
			j -= 64;
			//获得档位位数
			uint8_t tap = 0;
			for (; tap < 10; tap++)
			{
				if (EEPROM_MSG.analog_tap_pos[i * 10 + tap] == 0xFFFF) break;
			}
			//清空档位位值
			uint8_t byte_offset = j / 8; //字节偏移量
			uint8_t start_bit = j % 8; //起始位
			while (tap-- != 0) 
			{
				pt->tap_positions[byte_offset] &= ~(1 << start_bit);
				start_bit++;
				if (start_bit >= 8)
				{
					start_bit -= 8;
					byte_offset++;
				}
			}
			//置位档位位值
			if (Analogs[i] < 10)
			{
				uint8_t byte_offset = j / 8; //字节偏移量
				uint8_t bit = (j % 8) + Analogs[i]; //位偏移量
				while (bit >= 8)
				{
					byte_offset++;
					bit -= 8;
				}
				pt->tap_positions[byte_offset] |= (1 << bit);
			}
		}
	}
	//合并采集开关量
	GetKeysMask();
	for (size_t i = 0; i < 4; i++)
	{
		pt->keys[i] &= KeysMask[i];
		pt->keys[i] |= Keys[i];
	}
	pt->check_sum = CheckSum(&pTxbuf[1], sizeof(status_frame_t) - 2);
}

//解码从下级传来的连接序号帧
void DecodeLinkFr(uint8_t *pFr)
{
	link_t *pL = (link_t*)pFr;
	link_no_t new_ln = { .byte = pL->link_no };
	new_ln.now_ln++;
	if (new_ln.now_ln != link_no.now_ln) //更新当前的连接序号
	{
		link_no.byte = new_ln.byte;
		if (SysState.isTop == 0)
			SysState.isLink = 0;
	}
	
	if (SysState.isTop != 0) //向下发送连接确认帧
	{
		link_no.max_ln = link_no.now_ln;
//		if (SysState.isLink == 0)
		{	//向外(上)发送配置帧
			PackConfigFr();
		}
		PakeLinkAffirmFr();
		osSemaphoreRelease(ToDnSendSemHandle);
	}
	else PakeLinkNoFrAndTx(); //向上传递当前的连接序号
}
//解码从上级传来的连接确认帧
void DecodeLinkAffirmFr(uint8_t *pFr)
{
	link_t *pL = (link_t*)pFr;
	link_no_t new_ln = { .byte = pL->link_no };
	new_ln.now_ln--;
	if (new_ln.now_ln == link_no.now_ln) //向下发送连接确认帧
	{
		link_no.byte = new_ln.byte; //更新最大连接号
		PakeLinkAffirmFr();
		osSemaphoreRelease(ToDnSendSemHandle);
	}
	else
	{	//确认码出错,重新连接
		PakeLinkNoFrAndTx();
		SysState.isLink = 0;
	}
}
//解码从下级传来的系统状态帧
void DecodeStatusFr(uint8_t *pFr)
{
	if (SysState.isFr2Tx == 0)
	{	//向上传递状态帧
		status_frame_t *pStFr = (status_frame_t*)pFr;
		memcpy(DnAnalogs, pStFr->analogs, 8 * 2);
		memcpy(DnTapPos, pStFr->tap_positions, 4);
		memcpy(DnKeys, pStFr->keys, 4);
		PakeStatusFr(UpTxBuf);
		
		HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_SET);
		UD_Transmit(pUpUart, UpTxBuf, sizeof(status_frame_t));
		HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_RESET);
	}
	else
	{	//向上发送其它帧
		HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_SET);
		UD_Transmit(pUpUart, UpTxBuf, GetFrameLen(UpTxBuf[1]) + 1); //向上发送其它帧
		HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_RESET);
		SysState.isFr2Tx = 0;
	}
	if (SysState.isTop != 0)
	osMessagePut(UDP_MsgQueueHandle, (uint32_t)UpTxBuf, 0); //向外传递状态帧
}
TIM_HandleTypeDef *hOutAnalogTIM[] = { //0,1,2,3,4
	&htim4, &htim4, &htim4, &htim4, &htim8
	};
uint32_t OutAnalogChannel[] = { 
	TIM_CHANNEL_4, TIM_CHANNEL_3, TIM_CHANNEL_2, TIM_CHANNEL_1, TIM_CHANNEL_4
	};
TIM_HandleTypeDef *hOutOnoffTIM[] = { //0,1,2,3; 4,5,6,7,8,9
	&htim8, &htim8, &htim8, &htim5, 
	&htim1, &htim1, &htim2, &htim2, &htim3, &htim3
	};
uint32_t OutOnoffChannel[] = { 
	TIM_CHANNEL_3, TIM_CHANNEL_2, TIM_CHANNEL_1, TIM_CHANNEL_1, 
	TIM_CHANNEL_4, TIM_CHANNEL_1, TIM_CHANNEL_4, TIM_CHANNEL_3, TIM_CHANNEL_4, TIM_CHANNEL_3
	};
//获得传感器电阻的pwm值
uint16_t GetRPWM(uint8_t i, uint8_t j)
{
	if (out_analog_code == 1) return UpAnalogs[j]; //调整传感器电阻模式--只接通有用的R
	//out_analog_code = 0--规格化后编码0%~100%
	int pct = UpAnalogs[j]; //UpAnalogs[j]=0~1000=>0~100.0%
	for (uint8_t n = i * 10; n < 10 + i * 10; n++)
	{
		int dPct = pct - EEPROM_MSG.cal_pct[n];
		if (dPct > 0) continue;
		if (dPct == 0) return EEPROM_MSG.cal_out[n];
		//dPct < 0; out = OUT[n-1] + (OUT[n] - OUT[n-1]) / PCT[n] - PCT[n-1] * dPct;
		dPct = UpAnalogs[j] - EEPROM_MSG.cal_pct[n - 1];
		int dPCT = EEPROM_MSG.cal_pct[n] - EEPROM_MSG.cal_pct[n - 1];
		uint16_t out = EEPROM_MSG.cal_out[n - 1];
		int dOUT = EEPROM_MSG.cal_out[n] - out;
		return out + dOUT * dPct / dPCT; //dOUT有可能为负,其余均为正!
	}
	return 0;
}
//更新输出
void UpdateOut(void)
{
	//输出脉冲或电阻模拟量
	for (int i = 0; i < 5; i++)
	{
		uint8_t j = EEPROM_MSG.out_pos[i];
		if (j >= 0x80)
		{
			__HAL_TIM_SET_COMPARE(hOutAnalogTIM[i], OutAnalogChannel[i], 0); //脉冲
			continue;
		}
		uint16_t Tmax = EEPROM_MSG.freq_pwm_max[i];
		//使能电阻0,脉冲频率最大值为0!
		if (Tmax == 0)
		{
			for (i = 0; i < 3; i++) __HAL_TIM_SET_COMPARE(hOutAnalogTIM[i], OutAnalogChannel[i], 0); //除R00外其余短路
			uint16_t R0pwm = GetRPWM(0, j); //输出R0(5bit=>32-1)
			__HAL_TIM_SET_PRESCALER(hOutAnalogTIM[4], 0); //72M/1
			__HAL_TIM_SET_AUTORELOAD(hOutAnalogTIM[4], 1000 - 1); //f=72KHz
			__HAL_TIM_SET_COMPARE(hOutAnalogTIM[4], OutAnalogChannel[4], R0pwm);
			break;
		}
		else
		{
			if (Tmax < 3) Tmax = 3;
			int t = UpAnalogs[j] ? Tmax * 1000 / UpAnalogs[j] : 65536; //输出脉冲:72M分频7200每100us加1,频率范围:(3~65536)*100us=>3.3KHz~0.15Hz
			if (t > 65536) t = 65536;
			__HAL_TIM_SET_PRESCALER(hOutAnalogTIM[i], 7200 - 1); //72M/7200=10KHz
			__HAL_TIM_SET_AUTORELOAD(hOutAnalogTIM[i], t - 1); //f=10KHz/t,t=65536~Tmax,f=0.15Hz~Fmax
			__HAL_TIM_SET_COMPARE(hOutAnalogTIM[i], OutAnalogChannel[i], t / 2); //脉冲
		}
	}
	//输出开关量
	for (int i = 0; i < 10; i++)
	{
		uint8_t j = EEPROM_MSG.out_pos[i + 5];
		if (j >= 0x80)
		{
			__HAL_TIM_SET_COMPARE(hOutOnoffTIM[i], OutOnoffChannel[i], 0);
			continue;
		}
		uint16_t Pmax = EEPROM_MSG.freq_pwm_max[i + 5];
		if (Pmax == 0)
		{
			if (i < 4)//输出R1
			{
				uint16_t R1pwm = GetRPWM(1, j); //输出R1(6bit=>64-1)
				for (i = 0; i < 3; i++) __HAL_TIM_SET_COMPARE(hOutOnoffTIM[i], OutOnoffChannel[i], 0); //除R12外其余短路
				//i=3
				__HAL_TIM_SET_PRESCALER(hOutOnoffTIM[i], 0); //72M/1
				__HAL_TIM_SET_AUTORELOAD(hOutOnoffTIM[i], 1000 - 1); //f=72KHz
				__HAL_TIM_SET_COMPARE(hOutOnoffTIM[i], OutOnoffChannel[i], R1pwm);
				continue;
			}
			for (i = 4; i < 9; i++) //除R20外其余短路
			{
				if (i < 6) __HAL_TIM_SET_COMPARE(hOutOnoffTIM[i], OutOnoffChannel[i], 0);
				else __HAL_TIM_SET_COMPARE(hOutOnoffTIM[i], OutOnoffChannel[i], 65535);
			}
			//i=9
			uint16_t R2pwm = GetRPWM(2, j); //输出R2(6bit=>64-1)
			__HAL_TIM_SET_PRESCALER(hOutOnoffTIM[i], 0); //72M/1=72M
			__HAL_TIM_SET_AUTORELOAD(hOutOnoffTIM[i], 1000 - 1); //f=72M/1000=72KHz
			__HAL_TIM_SET_COMPARE(hOutOnoffTIM[i], OutOnoffChannel[i], R2pwm);
			return;
		}
		uint8_t s = j & 0x08; //取步进电机控制使能位
		uint8_t k = j >> 4; //取高3为--leds字节的位偏移
		j &= 0x07; //取低3位--leds[]偏移字节
		uint8_t on_off = UpLeds[j] & (1 << k);
		if (s != 0 && i >= 6) //步进电机控制开关
		{
			__HAL_TIM_SET_PRESCALER(hOutOnoffTIM[i], 9 - 1); //72M/9=8M
			__HAL_TIM_SET_AUTORELOAD(hOutOnoffTIM[i], 1000 - 1); //fpwm=8/1000us=8KHz
			osThreadResume(_UpdateStepTaskHandle); //更新步控位置
			break;
		}
		else //pwm控制开关输出
		{
			uint16_t pwm = on_off ? EEPROM_MSG.freq_pwm_max[i + 5] : 0;	//定时器为72M分频72每1us加1
			__HAL_TIM_SET_PRESCALER(hOutOnoffTIM[i], 72 - 1); //72M/72=1M
			__HAL_TIM_SET_AUTORELOAD(hOutOnoffTIM[i], 1000 - 1); //fpwm=1/1000us=1KHz
			__HAL_TIM_SET_COMPARE(hOutOnoffTIM[i], OutOnoffChannel[i], pwm);
		}
	}
}
//解码从上级传来的校准非线性电阻命令帧
void DecodeCalNonlRFr(uint8_t *pFr)
{
	command_frame_t *pt = (command_frame_t*)pFr;
	if (pt->link_no == link_no.now_ln) //pt->link_no不含最大连接数!
	{
		int j = pt->para / 10;
		if (j == 0) j = EEPROM_MSG.out_pos[0];
		else if (j == 1) j = EEPROM_MSG.out_pos[5];
		else j = EEPROM_MSG.out_pos[9];
		EEPROM_MSG.cal_pct[pt->para] = pt->para1;
		EEPROM_MSG.cal_out[pt->para] = UpAnalogs[j];
	}
	else
	{	//向下传递
		memcpy(DnTxBuf, pFr, sizeof(command_frame_t));
		osSemaphoreRelease(ToDnSendSemHandle);
	}
}
//解码从上级传来的指示帧
void DecodeIndicateFr(uint8_t *pFr)
{
	//向下传递
	memcpy(DnTxBuf, pFr, sizeof(indicate_frame_t));
	osSemaphoreRelease(ToDnSendSemHandle);
	
	indicate_frame_t *pt = (indicate_frame_t*)pFr;
	out_analog_code = pt->analog_code;
	memcpy(UpAnalogs, pt->analogs, 12 * 2);
	memcpy(UpLeds, pt->leds, 4);
	UpdateOut();
}
//解码从下级(上行)传来的配置帧
void DecodeUpConfigFr(uint8_t *pFr)
{
	memcpy(UpTxBuf, pFr, sizeof(config_t));
	HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_SET);
	UD_Transmit(pUpUart, UpTxBuf, sizeof(config_t));
	HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_RESET);
	if (SysState.isTop != 0)
		osMessagePut(UDP_MsgQueueHandle, (uint32_t)UpTxBuf, 0); //向外传递配置帧
}
//解码从上级传来的配置帧
void DecodeDnConfigFr(uint8_t *pFr)
{
	config_t *pt = (config_t*)pFr;
	if (pt->link_no == link_no.byte) //pt->link_no含最大连接数
	{
		memcpy(&EEPROM_MSG, &pt->eeprom_var, sizeof(EEPROM_MSG_STR) - 30 * 4);
		UpdateOut();
	}
	else
	{	//向下传递
		memcpy(DnTxBuf, pFr, sizeof(config_t));
		osSemaphoreRelease(ToDnSendSemHandle); //UD_Transmit(pDnUart, DnTxBuf, sizeof(config_t)); 
	}
}
//解码从上级下达的获得配置帧
void DecodeGetConfigFr(uint8_t *pFr)
{
	command_frame_t *pt = (command_frame_t*)pFr;
	if (pt->link_no == link_no.now_ln)
	{	
		PackConfigFr();
		return;
	}
	memcpy(DnTxBuf, pFr, sizeof(command_frame_t));
	osSemaphoreRelease(ToDnSendSemHandle);
}
//解码从上级传来的设置模拟量和档位量命令帧
void DecodeSetAnalogTapFr(uint8_t *pFr)
{
	command_frame_t *pt = (command_frame_t*)pFr;
	if (pt->link_no == link_no.now_ln)
	{
		EEPROM_MSG.analog_tap_pos[pt->para] = pt->para ? 0xFFFF : Angle[pt->para / 10];
		PackConfigFr();
		return;
	}
	memcpy(DnTxBuf, pFr, sizeof(command_frame_t));
	osSemaphoreRelease(ToDnSendSemHandle);
}
//解码从上级传来的保存配置帧
void DecodeSaveConfigFr(uint8_t *pFr)
{
	command_frame_t *pt = (command_frame_t*)pFr;
	if (pt->link_no == link_no.now_ln)
	{
		EE_SaveAllVar((uint16_t*)&EEPROM_MSG);
		return;
	}
	memcpy(DnTxBuf, pFr, sizeof(command_frame_t));
	osSemaphoreRelease(ToDnSendSemHandle);
}
//解码复位命令帧--无参数
void DecodeResetFr(uint8_t *pFr)
{
	memcpy(DnTxBuf, pFr, sizeof(command_frame_t));
	osSemaphoreRelease(ToDnSendSemHandle);
	osDelay(500);
	HAL_NVIC_SystemReset();
}

//描述: 解码通信协议
void DecodeComProtocol(unsigned char *pFrType/*[I]指向帧类型*/)
{
	uint8_t ft = *pFrType--;
	switch (ft)
	{
	case LINK_Fr:			//连接帧
		DecodeLinkFr(pFrType);
		break;
	case LINK_AFFIRM_Fr:	//连接确认帧
		DecodeLinkAffirmFr(pFrType);
		break;
	case STATUS_Fr:			//状态帧
		DecodeStatusFr(pFrType);
		break;
	case INDICAT_Fr:		//指示帧
		DecodeIndicateFr(pFrType);
		break;
	case UP_CONFIG_Fr:		//上行硬件配置帧
		DecodeUpConfigFr(pFrType);
		break;
	case DN_CONFIG_Fr:		//下行硬件配置帧
		DecodeDnConfigFr(pFrType);
		break;
	case GET_CONFIG_Fr:		//获得硬件配置帧
		DecodeGetConfigFr(pFrType);
		break;
	case SAVE_CONFIG_Fr:	//保存硬件配置帧
		DecodeSaveConfigFr(pFrType);
		break;
	case SET_ANALOG_TAP_Fr: //设置模拟量和档位量命令帧--参数:analog_tap_pos偏移量
		DecodeSetAnalogTapFr(pFrType);
		break;
	case RESET_Fr:			//复位命令帧--无参数
		DecodeResetFr(pFrType);
		break;
	case CAL_NONL_R_Fr:		//校准非线性帧--参数:电阻传感器序号,参数1:百分比
		DecodeCalNonlRFr(pFrType);
		break;
	default	:
		break;
	}
}
/*
********************************************************************************
** 函数名称 :	GetFrameLen	获得帧长度
** 描    述 :	从给定的帧类型，得到帧长度(不包含sync)。如果帧类型不合法，返回0
** 返    回 :	返回帧长度。如果帧类型不合法，返回0
********************************************************************************/
//描述: 获得给定帧类型的帧长度, -1=不包含sync
//返回: 0:无效帧, 其它:帧长
uint8_t GetFrameLen(uint8_t type/*[I]帧类型*/)
{
	switch (type)
	{
	case LINK_Fr:			//连接帧
		return sizeof(link_t) - 1;
	case LINK_AFFIRM_Fr:	//连接确认帧
		return sizeof(link_t) - 1;
	case STATUS_Fr:			//状态帧
		return sizeof(status_frame_t) - 1;
	case INDICAT_Fr:		//指示帧
		return sizeof(indicate_frame_t) - 1;
	case UP_CONFIG_Fr:		//上行硬件配置帧
		return sizeof(config_t) - 1;
	case DN_CONFIG_Fr:		//下行硬件配置帧
		return sizeof(config_t) - 1;
	case GET_CONFIG_Fr:		//获得硬件配置帧
		return sizeof(command_frame_t) - 1;
	case SAVE_CONFIG_Fr:	//保存硬件配置帧
		return sizeof(command_frame_t) - 1;
	case SET_ANALOG_TAP_Fr: //设置模拟量和档位量命令帧--参数:analog_tap_pos偏移量
		return sizeof(command_frame_t) - 1;
	case RESET_Fr:			//复位命令帧--无参数
		return sizeof(command_frame_t) - 1;
	case CAL_NONL_R_Fr:		//校准非线性帧--参数:电阻传感器序号,参数1:百分比
		return sizeof(command_frame_t) - 1;
	default:
		return 0;
	}
}
//描述: 解码1帧数据.支持帧格式为：SYNC[1B]+帧类型[1B]+id+数据+...+校验和[1B]。
//帧长（不含同步字节）:根据帧类型可获得。
//校验和:不含同步字节，之前数据相加得到。
static void DecodeFrameData(uint8_t *pByte, uint8_t size)
{
	while (size-- >=  4)	//4为最短帧长
	{
		if (*pByte++ != SYNC)
			continue;								//寻找同步头
		uint8_t len = GetFrameLen(*pByte); //帧长-1
		if ((len == 0) || (len > size))
			continue;								//帧类型不合法
		if (CheckSum(pByte, len - 1) != pByte[len - 1])
			continue;								//校验和不正确
		//指向pByte指向帧类型，len = 帧大小-1，size = SIZE-1
		DecodeComProtocol(pByte);
		size -= len; //size-len = SIZE-1-(帧大小-1) = SIZE-帧SIZE => 去掉一帧的数据
		pByte += len; //pByte+len = 指向帧类型+(帧长-1) = 指向sync+帧长 => 指向下一帧头
	}
}
#pragma endregion

#pragma region //============方法==============
#pragma region //------------重写方法-------------
uint8_t CheckSum(uint8_t *pByte, uint8_t len)
{
	uint8_t chk_sum = 0;
	while (len-- > 0)
	{
		chk_sum += *pByte++;
	}
	return chk_sum;
}
uint8_t UpGoMissing;
//描述: 读取1帧数据发生超时回调函数
void UD_ReadTimeoutCallBack(UartDriver *obj /*[I]注册过的串口对象*/)
{
	if (obj == pDnUart) 
	{
		if (SysState.isLink == 0 && SysState.isTop == 0)
		{
			PakeLinkNoFrAndTx(); //向上传递当前的连接序号
		}
		else
		{
			if (SysState.isFr2Tx == 0)
			{	//向上传递状态帧
				PakeStatusFr(UpTxBuf);
				HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_SET);
				UD_Transmit(pUpUart, UpTxBuf, sizeof(status_frame_t));				
				HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_RESET);
			}
			else
			{	//向上发送其它帧
				HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_SET);
				UD_Transmit(pUpUart, UpTxBuf, GetFrameLen(UpTxBuf[1]) + 1);
				HAL_GPIO_WritePin(EnUpTx_GPIO_Port, EnUpTx_Pin, GPIO_PIN_RESET);
				SysState.isFr2Tx = 0;
			}
			if (++UpGoMissing > 3 && link_no.now_ln != 0)
			{	//下连板撤除或断开!
				UpGoMissing = 0;
				link_no.byte = 0;
				SysState.isLink = 0;
				SysState.isTop = 0;
			}
		}
		if (SysState.isTop != 0)
		osMessagePut(UDP_MsgQueueHandle, (uint32_t)UpTxBuf, 0); //向外传递状态帧
		return;
	}
	if (obj == pUpUart && SysState.isTop == 0)
	{
		SysState.isTop = 1;
		link_no.max_ln = link_no.now_ln;
//		if (SysState.isLink == 0)
		{	//向外(上)发送配置帧
			PackConfigFr();
		}
		PakeLinkAffirmFr();
		osSemaphoreRelease(ToDnSendSemHandle);
	}
}
#pragma endregion

void RxFromDn_Task(void const * argument)
{
	osDelay(3000); //等待485识别完极性和网络连通
	UD_Register(&pDnUart, &huart1, DnRxBuf, DnFrBuf, UP_BUF_SIZE);
	UD_Init(pDnUart, TxDn_CpltSemHandle, RxDn_IdleSemHandle, 40, 3); //20ms收不到数据超时
	
	for (;;)
	{
		int len = UD_ReadFrameData(pDnUart);
		//解码帧数据
		DecodeFrameData(DnFrBuf, len);
		//向下发送数据
		if (osSemaphoreWait(ToDnSendSemHandle, 10) != osOK)
		{	//上位机无控制信号
			PakeLinkAffirmFr();
		}
		len = GetFrameLen(DnTxBuf[1]) + 1;
		HAL_GPIO_WritePin(EnDnTx_GPIO_Port, EnDnTx_Pin, GPIO_PIN_SET);
		UD_Transmit(pDnUart, DnTxBuf, len);
		HAL_GPIO_WritePin(EnDnTx_GPIO_Port, EnDnTx_Pin, GPIO_PIN_RESET);
	}
}

void RxFromUp_Task(void const * argument)
{
	osDelay(3000); //等待485识别完极性网络连通
	UD_Register(&pUpUart, &huart2, UpRxBuf, UpFrBuf, UP_BUF_SIZE);
	UD_Init(pUpUart, TxUp_CpltSemHandle, RxUp_IdleSemHandle, 100, 3); //100ms收不到上级数据超时
	
	for (;;)
	{
		int len = UD_ReadFrameData(pUpUart);
		SysState.isTop = 0;
		//解码帧数据
		DecodeFrameData(UpFrBuf, len);
	}
}

uint16_t StepPulse[8][4] =
{ 
	{ 12, 0, 0, 0 },
	{ 12, 0, 12, 0 },
	{ 0, 0, 12, 0 },
	{ 0, 12, 12, 0 },
	{ 0, 12, 0, 0},
	{ 0, 12, 0, 12},
	{ 0, 0, 0, 12},
	{ 12, 0, 0, 12}
};
void UpdateStepTask(void const * argument)
{
	int first = 1;
	for (;;)
	{
		osThreadSuspend(_UpdateStepTaskHandle);
		if (first)
		{
			__HAL_TIM_SET_AUTORELOAD(hOutOnoffTIM[6], 12 - 1); //fpwm=20KHz=>12*4=48us=>20.8KHz
			__HAL_TIM_SET_AUTORELOAD(hOutOnoffTIM[7], 12 - 1);
			__HAL_TIM_SET_AUTORELOAD(hOutOnoffTIM[8], 12 - 1);
			__HAL_TIM_SET_AUTORELOAD(hOutOnoffTIM[9], 12 - 1);
			for (size_t c = 0; c < 100; c++)
			{
				for (size_t s = 0; s < 8; s++)
				{
					for (size_t g = 0; g < 4; g++)
					{
						uint16_t pwm = EEPROM_MSG.freq_pwm_max[5 + 6 + g]*StepPulse[s][g] / 20000;
						__HAL_TIM_SET_COMPARE(hOutOnoffTIM[6 + g], OutOnoffChannel[6 + g], pwm);
					}
					osDelay(2);
				}
			}
		}
	}
}

#pragma endregion
